package Thread;

/*
 * 互斥锁
 * 当一个类中 使用多个synchronized锁定多个代码片段，并且指定的都是同一个同步监视器对象时
 * 这些代码片段之间就是互斥的，多个线程不能同时执行他们
 * */
public class SynchronizedDemo4 {
    public static void main(String[] args) {
        Foo foo = new Foo();
        Thread t1 = new Thread() {
            @Override
            public void run() {
                foo.methodA();
            }
        };

        Thread t2 = new Thread() {
            @Override
            public void run() {
                foo.methodB();
            }
        };

        t1.start();
        t2.start();
    }
}


class Foo {

    /*
     *
     * 因为 synchronized关键字修饰成员方法是，默认的同步监视器就是this(指代当前调用此方法的实例)
     * 所以当线程调用此这两个方法时，foo实例调用methodA的时候此时别的线程就不可以调用methodB因为此时的foo实例已经上锁
     *
     * 互斥的形成条件
     * 当两个方法的同步监视器都是this
     * 当两个方法都被synchronized关键字修饰
     * */


    public synchronized void methodA() {
        try {
            Thread t = Thread.currentThread();
            System.out.println(t.getName() + ":正在执行A方法 ");
            Thread.sleep(2000);
            System.out.println(t.getName() + "执行A方法完毕");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /*
     * 当将methodB方法中的synchronized注释掉，t1和t2线程调用moethodA的时候依然需要同步进行
     * 而使用foo调用methodb的时候就可以多个线程同时进行
     *
     * 在synchhronized中 并不是真正意义上 将foo这个对象上了锁
     * 而是在底层中在foo对象的旁边 打上一个标记
     * 只有当前所标记的线程可以执行foo对象中 被sunchronized关键字修饰的方法
     * */
    public void methodB() {
        try {
            // synchronized (this) {
            Thread t = Thread.currentThread();
            System.out.println(t.getName() + ":正在执行B方法 ");
            Thread.sleep(2000);
            System.out.println(t.getName() + "执行B方法完毕");
            // }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
